﻿using System;
using System.Collections.Generic;
using System.Linq;
using Sustainalytics.DataLayer;
using Sustainalytics.Entities;
using Sustainalytics.Utils;
using Sustainalytics.Replication.Publisher;
using Newtonsoft.Json;

namespace Sustainalytics.Portfolios.BL
{
    public class SubscribeToPortfolioManagement : ISubscribeToPortfolioManagement
    {
        private readonly ISubscribeToPortfolioRepository _subscribeRepo;
        private readonly ServiceBusPublisher _serviceBusPublisher;

        public static ISubscribeToPortfolioManagement GetInstance(ISubscribeToPortfolioRepository subRepository, ServiceBusPublisher serviceBusPublisher)
        {
            return new SubscribeToPortfolioManagement(subRepository, serviceBusPublisher);
        }

        public SubscribeToPortfolioManagement(ISubscribeToPortfolioRepository subRepository, ServiceBusPublisher serviceBusPublisher)
        {
            _subscribeRepo = subRepository;
            _serviceBusPublisher = serviceBusPublisher;
        }

        public bool UserHasSubscriptionToPortfolio(Guid id, Guid ownerUserId, Guid[] accountId)
        {
            return _subscribeRepo.ReadCount(p => p.PortfolioIds.Contains(id) && p.Enabled == true && p.UserId != ownerUserId && accountId.Contains(p.AccountId)) > 0;
        }

        public List<SubscribeToPortfolio> GetSubscriptions(PortfolioUserClaims userClaims)
        {
            return _subscribeRepo.GetSubscriptions(userClaims.UserId, userClaims.AccountId);
        }

        public void AddSubscribeToPortfolio(SubscribeToPortfolio subscribe)
        {
            _subscribeRepo.Insert(subscribe);
            _serviceBusPublisher.SendMessage(JsonConvert.SerializeObject(subscribe), ReplicationUtils.EntityType.SubscribeToPortfolio, ReplicationUtils.Operation.Insert);
        }

        public void UpdateSubscribeToPortfolio(SubscribeToPortfolio subscribe)
        {
            _subscribeRepo.Update(subscribe);
            _serviceBusPublisher.SendMessage(JsonConvert.SerializeObject(subscribe), ReplicationUtils.EntityType.SubscribeToPortfolio, ReplicationUtils.Operation.Update);
        }

        public void UpdateSubscribeState(Guid id, bool status)
        {
            _subscribeRepo.UpdateStatus(id, status);
            _serviceBusPublisher.SendMessage(JsonConvert.SerializeObject(new Tuple<Guid, bool>(id, status)), ReplicationUtils.EntityType.SubscribeToPortfolio, ReplicationUtils.Operation.UpdateStatus);
        }

        public void DeleteSubscribeToPortfolio(Guid subscribeId)
        {
            _subscribeRepo.Delete(subscribeId);
            _serviceBusPublisher.SendMessage(JsonConvert.SerializeObject(subscribeId), ReplicationUtils.EntityType.SubscribeToPortfolio, ReplicationUtils.Operation.Delete);
        }

        public void DeleteSubscriptionToPortfolio(Guid portfolioId)
        {
            var listSubs = _subscribeRepo.ReadWhere(x => x.PortfolioIds.Contains(portfolioId));
            UpdateSubscriptionList(portfolioId, listSubs);
        }

        public void UpdateSubsciptionsForPortfolio(Guid portfolioId, Guid userId)
        {
            var listSubs = _subscribeRepo.ReadWhere(x => x.PortfolioIds.Contains(portfolioId));
            UpdateSubscriptionList(portfolioId, listSubs.Where(subs => subs.UserId != userId));
        }

        private void UpdateSubscriptionList(Guid portfolioId, IEnumerable<SubscribeToPortfolio> listSubs)
        {
            foreach (var subs in listSubs)
            {
                subs.PortfolioIds.Remove(portfolioId);
                if (subs.PortfolioIds.Any())
                {
                    _subscribeRepo.CreateOrUpdate(subs);
                    _serviceBusPublisher.SendMessage(JsonConvert.SerializeObject(subs), ReplicationUtils.EntityType.SubscribeToPortfolio, ReplicationUtils.Operation.CreateOrUpdate);
                }
                else
                {
                    _subscribeRepo.Delete(subs.Id);
                    _serviceBusPublisher.SendMessage(JsonConvert.SerializeObject(subs.Id), ReplicationUtils.EntityType.SubscribeToPortfolio, ReplicationUtils.Operation.Delete);
                }
            }
        }
    }
}
